/**
 * 简洁高效的并发控制器
 * 使用滑动窗口算法控制并发执行数量
 */
export class ConcurrencyController {
	/**
	 * 并发执行任务，控制最大并发数
	 * @param tasks 任务数组
	 * @param concurrency 最大并发数
	 * @param stopOnError 是否在遇到错误时停止所有任务
	 * @returns Promise<void>
	 */
	static async execute<T>(
		tasks: (() => Promise<T>)[],
		concurrency: number,
		stopOnError: boolean = false
	): Promise<(T | Error)[]> {
		const results: (T | Error)[] = new Array(tasks.length);
		const executing: Promise<void>[] = [];
		let index = 0;
		let hasError = false;

		const executeTask = async (taskIndex: number): Promise<void> => {
			try {
				results[taskIndex] = await tasks[taskIndex]();
			} catch (error) {
				results[taskIndex] = error instanceof Error ? error : new Error(String(error));
				if (stopOnError) {
					hasError = true;
				}
			}
		};

		// 滑动窗口并发控制
		while (index < tasks.length && !hasError) {
			// 填充执行池到并发限制
			while (executing.length < concurrency && index < tasks.length && !hasError) {
				const taskIndex = index++;
				const promise = executeTask(taskIndex).then(() => {
					// 任务完成后从执行池中移除
					const idx = executing.indexOf(promise);
					if (idx > -1) executing.splice(idx, 1);
				});
				executing.push(promise);
			}

			// 等待至少一个任务完成
			if (executing.length > 0) {
				await Promise.race(executing);
			}
		}

		// 等待所有剩余任务完成
		await Promise.all(executing);

		return results;
	}

	/**
	 * 批处理并发执行（更简单但可能效率稍低）
	 * @param tasks 任务数组
	 * @param batchSize 批处理大小
	 * @param stopOnError 是否在遇到错误时停止
	 * @returns Promise<(T | Error)[]>
	 */
	static async executeBatch<T>(
		tasks: (() => Promise<T>)[],
		batchSize: number,
		stopOnError: boolean = false
	): Promise<(T | Error)[]> {
		const results: (T | Error)[] = new Array(tasks.length);

		for (let i = 0; i < tasks.length; i += batchSize) {
			const batchEnd = Math.min(i + batchSize, tasks.length);
			const batchPromises: Promise<void>[] = [];

			for (let j = i; j < batchEnd; j++) {
				const taskIndex = j;
				const promise = tasks[taskIndex]()
					.then(result => {
						results[taskIndex] = result;
					})
					.catch(error => {
						results[taskIndex] = error instanceof Error ? error : new Error(String(error));
						if (stopOnError) {
							throw error;
						}
					});
				batchPromises.push(promise);
			}

			try {
				await Promise.all(batchPromises);
			} catch (error) {
				if (stopOnError) {
					throw error;
				}
			}
		}

		return results;
	}

	/**
	 * 简单的并发限制器（最简洁的实现）
	 * @param tasks 任务数组
	 * @param concurrency 最大并发数
	 * @returns Promise<T[]>
	 */
	static async limit<T>(
		tasks: (() => Promise<T>)[],
		concurrency: number
	): Promise<T[]> {
		const results: T[] = [];
		
		for (let i = 0; i < tasks.length; i += concurrency) {
			const batch = tasks.slice(i, i + concurrency);
			const batchResults = await Promise.all(batch.map(task => task()));
			results.push(...batchResults);
		}

		return results;
	}
}
